package com.bjpowernode.boss.mvc.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bjpowernode.boss.constants.KeyConst;
import com.bjpowernode.boss.domain.PmsMenu;
import com.bjpowernode.boss.domain.PmsOperator;
import com.bjpowernode.boss.enums.ajax.Code;
import com.bjpowernode.boss.exception.BossException;
import com.bjpowernode.boss.mapper.PmsOperatorMapper;
import com.bjpowernode.boss.mvc.model.dto.OperatorLoginDto;
import com.bjpowernode.boss.mvc.model.dto.PmsMenuDto;
import com.bjpowernode.boss.mvc.model.query.OperatorLoginQuery;
import com.bjpowernode.boss.mvc.service.OperatorService;
import com.bjpowernode.boss.utils.JwtUtil;
import com.bjpowernode.boss.utils.RedisUtil;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * 操作服务实现类
 */
@Service
public class OperatorServiceImpl extends ServiceImpl<PmsOperatorMapper, PmsOperator> implements OperatorService {

    @Resource
    private PmsOperatorMapper pmsOperatorMapper;

    @Resource
    private RedisUtil redisUtil;

    @Override
    public OperatorLoginDto operatorLogin(OperatorLoginQuery operatorLoginQuery) {
        // 查询用户  根据用户id 唯一索引
        PmsOperator pmsOperator = pmsOperatorMapper.selectOne(new LambdaQueryWrapper<PmsOperator>().eq(PmsOperator::getLoginName, operatorLoginQuery.getLoginName()));
        // 查询是否存在该数据
        if (pmsOperator == null) {
            // 用户不存在 , 抛出异常
            throw new BossException(Code.UNKNOWN);
        }

        // 用户存在
        // (登录密码 + 数据库的salt) 后 进行md5加密  ----> 跟数据库用户登录密码进行置比
        // operatorLoginQuery.getLoginPwd() + pmsOperator.getSalt()
        String requestLoginPwdMd5 = DigestUtil.md5Hex(operatorLoginQuery.getLoginPwd() + pmsOperator.getSalt());
        // 置比
        if (!requestLoginPwdMd5.equals(pmsOperator.getLoginPwd())) {
            // 不相等 , 抛出异常
            throw new BossException(Code.OPERATOR_LOGIN_ERR);
        }

        // 表示登录成功 , 生成jwt
        JSONObject userJson = new JSONObject();
        userJson.set("operatorId", pmsOperator.getId());
        //indentFactor – 每层缩进空格数
        String jwt = JwtUtil.createJwt(userJson.toJSONString(0));

        // 将获取到的jwt 存储到redis中
        JSONObject user = new JSONObject();
        user.set("operatorId", pmsOperator.getId());
        user.set("jwt", jwt);
        user.set("loginTime", new SimpleDateFormat("yyyyMMddHHmmss"));
        String loginKey = KeyConst.OPERATOR_LOGIN + pmsOperator.getId();
        redisUtil.setValue(loginKey, user.toJSONString(0));

        // 查询redis 的jwt
        String loginJsonVal = redisUtil.getValue(loginKey);
        // 判断是否存入成功 , 失败抛出异常
        if (StrUtil.isBlank(loginJsonVal)) {
            throw new BossException(Code.OPERATOR_LOGIN_REDIS_ERR);
        }

        // 返回dto对象
        return OperatorLoginDto
                .builder()
                .operatorId(pmsOperator.getId())
                .showName(pmsOperator.getShowName())
                .jwt(jwt)
                .build();
    }

    @Override
    public List<PmsMenuDto> loadMenusByOperatorId(Long operatorId) {
        // 根据 operatorId 查询该操作员得所有 菜单
        List<PmsMenu> pmsMenuList = pmsOperatorMapper.loadMenusByOperatorId(operatorId);

        // 遍历 pmsMenuList , 将里面is_leaf 是 no 的数据 存入dto中
        List<PmsMenuDto> menus = new ArrayList<>();
        for (PmsMenu pmsMenu : pmsMenuList) {

            if ("NO".equalsIgnoreCase(pmsMenu.getIsLeaf())){
                // no ==> 表示其是submenu
                PmsMenuDto subMenu = new PmsMenuDto();
                subMenu.setId(pmsMenu.getId());
                subMenu.setName(pmsMenu.getName());
                subMenu.setNumber(pmsMenu.getNumber());
                subMenu.setUrl(pmsMenu.getUrl());
                subMenu.setLeaf(pmsMenu.getIsLeaf());
                subMenu.setItems(new ArrayList<>());
                // 添加到 dto
                menus.add(subMenu);
            }
            // 将 is_leaf是 yes 的值 存储到 dto的 items中
            if ("YES".equalsIgnoreCase(pmsMenu.getIsLeaf())) {
                // yes ==> 表示其是 items
                PmsMenuDto item = new PmsMenuDto();
                item.setId(pmsMenu.getId());
                item.setName(pmsMenu.getName());
                item.setNumber(pmsMenu.getNumber());
                item.setUrl(pmsMenu.getUrl());
                item.setLeaf(pmsMenu.getIsLeaf());
                // 添加到 dto 对应的menu下的 items中
                menus.get(menus.size() - 1).getItems().add(item);
            }
        }
        return menus;
    }

    @Override
    public void logout(Integer operatorId) {
        if (!redisUtil.delKey(KeyConst.OPERATOR_LOGIN + operatorId)) {
            throw new BossException(Code.UNKNOWN);
        }
    }
}
